package com.nowcoder.community.service;

import com.nowcoder.community.dao.AlphaDao;
import com.nowcoder.community.dao.DiscussPostMapper;
import com.nowcoder.community.dao.UserMapper;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.util.CommunityUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Date;

/**
 * @author szq
 * @create 2023-01-18 14:14
 * @description Spring入门案例
 */
@Service
//@Scope("prototype")  // 每次获取都是不同的对象
@Slf4j
public class AlphaService implements BeanNameAware, ApplicationContextAware, InitializingBean {

    @Autowired
    private AlphaDao alphaDao;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DiscussPostMapper discussPostMapper;


    public String find() {
        return alphaDao.select();
    }

    public AlphaService() {
        System.out.println("第一步：实例化 AlphaService");
    }

    @Autowired
    public void setName(@Value("JAVA_HOME") String dir) {
        System.out.println("第二步：属性注入" + dir);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("第三步：检查是否实现Aware接口 -》 实现BeanNameAware接口，" +
                "获取BeanName:" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("第三步：检查是否实现Aware接口 -》 实现ApplicationContextAware接口，" +
                "ApplicationContext:" + applicationContext.getClass().getSimpleName());
    }

    @PostConstruct
    public void init() {
        System.out.println("第五步：初始化 AlphaService");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("第六步：InitializingBean’s afterPropertiesSet");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("第九步：销毁 AlphaService");
    }

    /**
     * 演示事务
     * REQUIRED：支持当前事务（外部事务），如果不存在则创建新事务
     * REQUIRES_NEW：创建一个新事务，并且暂停当前事务（外部事务）
     * SUPPORTS：支持使用当前事务，如果当前事务不存在，则不使用事务
     * NESTED：如果当前存在事务（外部事务），则嵌套在该事务中执行（独立的提交和回滚），否则就和REQUIRED一样
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public Object save1() {
        // 新增用户
        User user = new User();
        user.setUsername("alpha");
        user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
        user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
        user.setEmail("alpha@qq.com");
        user.setHeaderUrl("https://image.nowcoder.com/head/99t.png");
        user.setCreateTime(new Date());
        userMapper.insert(user);
        // 新增帖子
        DiscussPost post = new DiscussPost();
        post.setTitle("Hello");
        post.setContent("新人报道！");
        post.setCreateTime(new Date());
        post.setUserId(user.getId());
        discussPostMapper.insert(post);

        Integer.parseInt("abc");
        return "ok";
    }

    @Autowired
    private TransactionTemplate transactionTemplate;

    public Object save2() {
        //the transaction settings can be set here explicitly if so desired
        // 设置隔离级别
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        // 设置事务传播行为
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 30 seconds
        transactionTemplate.setTimeout(30);
        return transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 新增用户
                User user = new User();
                user.setUsername("beta");
                user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
                user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
                user.setEmail("beta@qq.com");
                user.setHeaderUrl("https://image.nowcoder.com/head/99t.png");
                user.setCreateTime(new Date());
                userMapper.insert(user);
                // 新增帖子
                DiscussPost post = new DiscussPost();
                post.setTitle("你好");
                post.setContent("我是新人！");
                post.setCreateTime(new Date());
                post.setUserId(user.getId());
                discussPostMapper.insert(post);
                Integer.parseInt("abc");
                return "ok";
            }
        });
    }

    // @Async 让该方法在多线程的环境下,被异步的调用
    @Async
    public void execute1() {
        log.debug("execute1...");
    }

    /*@Scheduled(initialDelay = 10000, fixedRate = 1000)
    public void execute2() {
        log.debug("execute2...");
    }*/
}
